#pragma once
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <poll.h>
#include <unistd.h>
#include <iostream>
#include <vector>

#include "users.hpp"

#define USER_LIMIT 5
class server
{
public:
    server(int port)
        :_port(port),_pollfd_vec(1)
    {
        _listenfd = socket(AF_INET,SOCK_STREAM,0);
        if(_listenfd == -1)
        {
            std::cout << "socket调用失败！" << std::endl;
            exit(-1);
        }
        // int old_option = fcntl(_listenfd,F_GETFL);
        // int new_option = old_option | O_NONBLOCK;
        // fcntl(_listenfd,F_SETFL,new_option);
        int val = 1;
        setsockopt(_listenfd,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(val));
        struct sockaddr_in server;
        memset(&server,0,sizeof(server));
        server.sin_family = AF_INET;
        server.sin_addr.s_addr = inet_addr("0.0.0.0");
        server.sin_port = htons(_port);
        int n = bind(_listenfd,(const struct sockaddr *)&server,sizeof(server));
        if(n == -1)
        {
            std::cout << "bind调用失败！" << std::endl;
            exit(-1);
        }

        n = listen(_listenfd,5);
        if(n == -1)
        {
            std::cout << "listen调用失败！" << std::endl;
        }
    }

    void start()
    {
        // for(int i=1;i<_pollfd_vec.size();i++)
        // {
        //     _pollfd_vec[i].fd = -1;
        //     _pollfd_vec[i].events = 0;
        // }
        _pollfd_vec[0].fd = _listenfd;
        _pollfd_vec[0].events = POLLIN | POLLERR;
        _pollfd_vec[0].revents = 0;
        while(true)
        {
            int ret = poll(_pollfd_vec.data(),_pollfd_vec.size(),-1);
            // std::cout << "正在监听的套接字个数:" << _pollfd_vec.size() << std::endl;
            // std::cout << "已经就绪的事件个数:" << ret << std::endl;
            if(ret == -1)
            {
                std::cout << "poll调用失败!" << std::endl;
                exit(-1);
            }
            for(int i=0;i<USER_LIMIT + 1;i++)
            {
                // 如果事件触发并且是监听套接字
                if(_pollfd_vec[i].fd == _listenfd && _pollfd_vec[i].revents & POLLIN)
                {
                    // accept接收连接
                    struct sockaddr_in client;
                    socklen_t len = sizeof(client);
                    int sockfd = accept(_listenfd,(struct sockaddr *)&client,&len);
                    std::cout << "获取到客户端套接字:" << sockfd << std::endl;
                    if(sockfd == -1)
                    {
                        std::cout << "accept调用失败!" << std::endl;
                        break;
                    }
                    // 如果连接的用户过多则关闭连接
                    if(_pollfd_vec.size() > USER_LIMIT+1)
                    {
                        const char *buffer = "负载用户过多！强制关闭新连接的用户！";
                        std::cout << buffer << std::endl;
                        send(sockfd,buffer,strlen(buffer),0);
                        close(sockfd);
                        continue;
                    }
                    // 创建用户对象并注册事件
                    _um.create_user(_pollfd_vec,sockfd);
                    std::cout << "创建了一个用户对象，用户uid为: " << _um.get_uid_by_sockfd(sockfd) << std::endl; 
                }
                else if(_pollfd_vec[i].revents & POLLRDHUP)
                {
                    
                }
                else if(_pollfd_vec[i].revents & POLLIN)
                {
                    int sockfd = _pollfd_vec[i].fd;
                    size_t uid = _um.get_uid_by_sockfd(sockfd);
                    users_t user = _um.get_by_uid(uid);
                    char buffer[1024] = {0};
                    int n = recv(sockfd,buffer,sizeof(buffer)-1,0);
                    std::cout << "接收到来自用户uid: " << uid << " 的消息:" << buffer << std::endl;
                    if(n > 0)
                    {
                        strcpy(user->get_buffer(),buffer);
                        // 收到了数据，注册一个写事件
                        for(int j=1;j<_pollfd_vec.size();j++)
                        {
                            //if(_pollfd_vec[j].fd == sockfd) continue;
                            _pollfd_vec[j].events |= ~POLLIN;
                            _pollfd_vec[j].events |= POLLOUT;
                        }
                    }
                }

                else if(_pollfd_vec[i].revents & POLLOUT)
                {
                    int sockfd = _pollfd_vec[i].fd;
                    size_t uid = _um.get_uid_by_sockfd(sockfd);
                    users_t user = _um.get_by_uid(uid);

                    for(int j=1;j<_pollfd_vec.size();j++)
                    {
                        if(strlen(user->get_buffer()) == 0 || _pollfd_vec[j].fd == sockfd) continue;
                        send(_pollfd_vec[j].fd,user->get_buffer(),strlen(user->get_buffer()),0);
                        _pollfd_vec[j].events |= ~POLLOUT;
                        _pollfd_vec[j].events |= POLLIN;
                    }
                    
                    user->set_buffer_empty();

                }
            }
        }
    }
protected:
    int _listenfd;
    int _port;
    std::vector<pollfd> _pollfd_vec;
    users_manamger _um;
};